#include <webx/sess.h>
#include <webx/route.h>
#include <dbentity/T_XG_USER.h>
#include <dbentity/T_XG_NOTE.h>
#include <dbentity/T_XG_CODE.h>
#include <dbentity/T_XG_DBETC.h>
#include <dbentity/T_XG_PARAM.h>

class CheckLogin : public webx::ProcessBase
{
protected:
	int process();
};

HTTP_WEBAPP(CheckLogin)

int CheckLogin::process()
{
	int res = XG_OK;
	int timeout = 1800;
	string sid = webx::GetSessionId(request);

	param_string(flag);

	if (flag == "U")
	{
		checkSession(sid);

		try
		{
			checkSystemRight();

			token->setTimeout(1800);
		}
		catch(Exception e)
		{
		}
	}
	else if (flag == "Q")
	{
		checkSession(sid);

		token->disable();
	}
	else if (flag == "C")
	{
		checkLogin(sid);

		json = token->toJson();

		if (token->getIcon().empty()) json["icon"] = "/res/img/user/user.png";

		try
		{
			checkSystemRight(token->getGrouplist());

			token->setTimeout(1800);
		}
		catch(Exception e)
		{
		}
	}
	else
	{
		res = XG_PARAMERR;

		param_string(user);
		param_string(password);

		CT_XG_USER tab;
		sp<DBConnect> dbconn = webx::GetDBConnect();

		if (user.empty() || password.empty())
		{
			param_string(mail);
			param_string(code);

			stdx::tolower(mail);
			stdx::tolower(code);

			if (sid.empty()) return simpleResponse(XG_TIMEOUT);
			
			if (mail.empty() || code.empty() || mail.find('@') == string::npos) return simpleResponse(XG_PARAMERR);

			checkSession(sid);

			if (mail != token->getMail() || code != token->getExtdata("code"))
			{
				return simpleResponse(token->checkTimes() > 0 ? XG_PARAMERR : XG_AUTHFAIL);
			}

			string dbid;
			string name = mail.substr(0, mail.find('@'));

			user = mail;

			tab.init(dbconn);

			auto GetDataId = [](sp<DBConnect> dbconn){
				string dbid;
				string sqlcmd = "SELECT ID FROM T_XG_DBETC WHERE ENABLED>1 ORDER BY STRESS ASC LIMIT 1";

				if (dbconn->select(dbid, sqlcmd) < 0) throw Exception(XG_SYSERR);
				
				return dbid;
			};
			
			auto UpdateDataStress = [](sp<DBConnect> dbconn, const string& dbid){
				if (dbid.length() > 0) dbconn->execute("UPDATE T_XG_DBETC SET STRESS=STRESS+STEP WHERE ID=?", dbid);
			};

			if (!tab.findWhere("MAIL=?", mail))
			{
				LogTrace(eIMP, "user[" + user + "] login failed");
				
				return simpleResponse(XG_SYSERR);
			}

			if (tab.next())
			{
				LogTrace(eIMP, "user[" + user + "][" + sid + "] login success");

				res = XG_OK;
			}
			else if ((dbid = GetDataId(dbconn)).empty())
			{
				res = XG_SYSERR;
			}
			else
			{
				LogTrace(eIMP, "user[" + user + "] does not exist");
				
				tab.dbid = dbid;
				tab.user = user;
				tab.name = name;
				tab.mail = mail;
				tab.level = "0";
				tab.enabled = "1";
				tab.password = "";
				tab.language = "CN";
				tab.grouplist = "normal";
				tab.statetime.update();
				
				if ((res = tab.insert()) >= 0)
				{
					LogTrace(eIMP, "create user[" + user + "] success");

					UpdateDataStress(dbconn, dbid);
					webx::InitNewUser(user);

					res = XG_OK;
				}
			}

			if (res > 0) json["user"] = tab.user.val();
		}
		else if (webx::IsFileName(user))
		{
			tab.init(dbconn);
			
			string mail = user;

			if (!tab.findWhere("USER=? OR MAIL=?", user, stdx::tolower(mail)))
			{
				LogTrace(eIMP, "user[" + user + "] login failed");
				
				return simpleResponse(XG_SYSERR);
			}

			if (tab.next())
			{
				int times = 5;
				int timeout = 600;

				token = newsp<LoginToken>(webx::GetSession("LOGINLIMIT[" + tab.user.val() + "]", timeout));
	
				if ((times = token->checkTimes(times)) <= 0)
				{
					LogTrace(eIMP, "user[" + user + "] login frequently");

					token->setTimeout(timeout);

					res = XG_AUTHFAIL; 
				}
				else
				{
					if (password == tab.password.val())
					{
						if (tab.enabled.val() < 1)
						{
							LogTrace(eIMP, "user[" + user + "] disabled");

							res = XG_NOTFOUND;
						}
						else
						{
							LogTrace(eIMP, "user[" + user + "] login success");

							res = XG_OK;
						}
					}
					else
					{
						LogTrace(eIMP, "user[" + user + "] login password error");

						json["timeout"] = timeout;

						res = XG_AUTHFAIL;
					}
				}

				json["times"] = times;
			}
			else
			{
				LogTrace(eIMP, "user[" + user + "] does not exist");

				res = XG_NOTFOUND;
			}

			if (res > 0) json["user"] = tab.user.val();
		}

		if (res == XG_OK)
		{
			string val = webx::GetParameter("LOGIN_TIMEOUT");

			timeout = val.length() > 0 ? (int)(stdx::atof(val.c_str()) * 24 * 3600) : 7 * 24 * 3600;

			try
			{
				checkSystemRight(tab.grouplist.val());

				timeout = 1800;
			}
			catch(Exception e)
			{
				if (timeout < 600) timeout = 600;
			}

			if (token) token->disable();

			token = LoginToken::Create(timeout);

			if (token->update(tab))
			{
				webx::SetSessionId(response, token->getSessionId());
			}
			else
			{
				res = XG_SYSERR;
			}
		}
	}

	json["code"] = res;
	out << json;
	
	return XG_OK;
}